package com.schtkc.fishingmaster.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.schtkc.fishingmaster.entity.User;
import com.schtkc.fishingmaster.entity.m.R;
import com.schtkc.fishingmaster.entity.m.UserAccessToken;
import com.schtkc.fishingmaster.entity.m.UserPhonePwd;
import com.schtkc.fishingmaster.entity.m.UserWithToken;
import com.schtkc.fishingmaster.mapper.UserAccessTokenMapper;
import com.schtkc.fishingmaster.mapper.UserMapper;
import com.schtkc.fishingmaster.utils.Constants;
import com.schtkc.fishingmaster.utils.Helper;
import com.schtkc.fishingmaster.utils.Message;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.Date;
import java.util.UUID;

/**
 * (User)表控制层
 *
 * @author makejava
 * @since 2024-11-03 00:23:10
 */
@RestController
@RequestMapping("users")
public class UsersController {
    /**
     * 服务对象
     */
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;


    private final Gson gson = new Gson();

    @ApiOperation("创建用户")
    @PostMapping("/create")
    public R create(@RequestBody User user) {
        int result = userMapper.insert(user);
        return new R(result, result == 1 ? Message.createSucceed : Message.createFailed);
    }

    @ApiOperation("获取所有用户信息")
    @GetMapping("/queryList")
    public R queryList() {
        return new R(Message.ok, "success", userMapper.selectList(null));
    }

    @ApiOperation("通过userId查询用户信息")
    @PostMapping("/queryById")
    public R queryById(@RequestBody User user) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getId, user.getId());
        return new R(Message.ok, Message.querySucceed, userMapper.selectList(wrapper));
    }

//    @ApiOperation("通过phone查询用户信息")
//    @PostMapping("/queryByPhone")
//    public R queryByPhone(@RequestBody ModelOnlyPhone user) {
//        QueryWrapper<User> wrapper = new QueryWrapper<>();
//        wrapper.lambda().eq(User::getPhone, user.getPhone());
//        return new R(Message.ok, Message.querySucceed, userMapper.selectList(wrapper));
//    }

    @ApiOperation("通过userId删除用户")
    @DeleteMapping("/deleteById")
    public R deleteById(@RequestBody User user) {
        System.out.println("delete ShopProductOrder");
        System.out.println(user.toString());
        if (Helper.isIdInvalid(user.getId())) {
            return new R(Message.err, Message.idInvalid);
        }
        //查询是否存在该条数据
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getId, user.getId());
        int count = userMapper.selectCount(wrapper);
        if (count <= 0)
            return new R(Message.err, Message.deleteFailNoData);
        //数据存在，执行删除
        int result = userMapper.deleteById(user.getId());
        return new R(result, result == 1 ? Message.deleteSucceed : Message.deleteFailed);
    }


    @ApiOperation("删除所有用户")
    @DeleteMapping("/deleteAll")
    public R deleteAll() {
        System.out.println("delete ShopProductOrder");
        //查询是否存在该条数据
        //数据存在，执行删除
        int result = userMapper.delete(null);
        return new R(result, result == 1 ? Message.deleteSucceed : Message.deleteFailed);
    }


    @ApiOperation("手机号密码注册")
    @PostMapping("/registerByPhonePwd")
    public R registerByPhonePwd(@RequestBody UserPhonePwd user) {
        System.out.println("手机号密码注册");
        System.out.println(user);
        if (Helper.isEmpty(user.getPhone())) {
            return new R(Message.err, String.format(Message.cantNull, "手机号码"));
        }
        if (Helper.isEmpty(user.getPassword())) {
            return new R(Message.err, String.format(Message.cantNull, "密码"));
        }

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getPhone, user.getPhone());
        int count = userMapper.selectCount(wrapper);
        if (count > 0) {
            return new R(Message.err, Message.phoneBound);
        }
        User newUser = new User();
//        newUser.setStatus(1);
        userMapper.insert(newUser);
        System.out.println("注册新用户成功");

        QueryWrapper<User> wrapperGetId = new QueryWrapper<>();
        wrapperGetId.select("id").eq("phone", user.getPhone());

        User userOnlyId = userMapper.selectOne(wrapperGetId);
        System.out.println("从数据库中读取新用户id");
        System.out.println(userOnlyId.toString());
        newUser.setId(userOnlyId.getId());

        String token = createToken(newUser);
        //将token存入redis
        redisTemplate.opsForValue().set(token, newUser.getId().toString());
        redisTemplate.opsForValue().set(Constants.FM_USER + newUser.getId().toString(), token);
//
        UserWithToken userWithToken = new UserWithToken(newUser, token);

        return new R(Message.ok, Message.registerSuc, Collections.singletonList(userWithToken));
    }

   /* @ApiOperation("手机号密码验证码注册")
    @PostMapping("/registerByPhonePwdVCode")
    public R registerByPhonePwdVCode(@RequestBody UserWithVCode user) {
        System.out.println("手机号密码验证码注册");
        System.out.println(user);
        if (Helper.isPhoneInvalid(user.getPhone())) {
            return new R(Message.err, Message.phoneInvalid);
        }
        if (Helper.isEmpty(user.getPassword())) {
            return new R(Message.err, String.format(Message.cantNull, "密码"));
        }
        //验证码为空或者不等于6
        if (Helper.isVCodeInvalid(user.getVerifyCode())) {
            return new R(Message.err, Message.vCodeInvalid);
        }
        //从数据库校验验证码
        QueryWrapper<VerifyCode> codeWrapper = new QueryWrapper<>();
        codeWrapper.lambda().eq(VerifyCode::getPhone, user.getPhone())
                .eq(VerifyCode::getCodeType, Constants.SMS_CODE_TYPE.REGISTER);
        if (codeMapper.selectCount(codeWrapper) <= 0) {
            System.out.println("没有获取过验证码");
            return new R(Message.err, Message.vCodeNotExists);
        }
        VerifyCode codeDb = codeMapper.selectOne(codeWrapper);
        if (!user.getVerifyCode().equals(codeDb.getCode())) {
            System.out.println("验证码不匹配");
            return new R(Message.err, Message.vCodeErr);
        }
        User newUser = new User();
        newUser.setStatus(1);
        newUser.setPhone(user.getPhone());
        newUser.setPassword(user.getPassword());

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getPhone, user.getPhone());
        int count = userMapper.selectCount(wrapper);
        if (count > 0) {
            return new R(Message.err, Message.phoneBound);
        }

        userMapper.insert(newUser);
        System.out.println("注册新用户成功");

        QueryWrapper<User> wrapperGetId = new QueryWrapper<>();
        wrapperGetId.select("id").eq("phone", user.getPhone());

        User userOnlyId = userMapper.selectOne(wrapperGetId);
        System.out.println("从数据库中读取新用户id");
        System.out.println(userOnlyId.toString());
        newUser.setId(userOnlyId.getId());

        String token = createToken(newUser);
        //将token存入redis
        redisTemplate.opsForValue().set(token, newUser.getId().toString());
        redisTemplate.opsForValue().set(Constants.KDSH + newUser.getId().toString(), token);

        UserWithToken userWithToken = new UserWithToken(newUser, token);

        return new R(Message.ok, Message.registerSuc, Collections.singletonList(userWithToken));
    }
*/

  /*  @ApiOperation("手机号密码登录")
    @PostMapping("/loginByPhonePwd")
    public R loginByPhonePwd(@RequestBody UserPhonePwd user) {
        System.out.println("手机号密码登录");
        System.out.println(user);
        if (Helper.isEmpty(user.getPhone())) {
            return new R(Message.err, String.format(Message.cantNull, "手机号码"));
        }
        if (Helper.isEmpty(user.getPassword())) {
            return new R(Message.err, String.format(Message.cantNull, "密码"));
        }

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getPhone, user.getPhone());
        int count = userMapper.selectCount(wrapper);
        if (count <= 0) {
            System.out.println("该手机号用户不存在");
            return new R(Message.err, Message.userDontExist);
        }
        wrapper.lambda().eq(User::getPassword, user.getPassword());
        int count2 = userMapper.selectCount(wrapper);
        if (count2 <= 0) {
            System.out.println("密码错误");
            return new R(Message.err, Message.errPwd);
        }
        User userDb = userMapper.selectOne(wrapper);

        System.out.println("登录成功");

        String token = createToken(userDb);
        //将token存入redis
        redisTemplate.opsForValue().set(token, userDb.getId().toString());
        redisTemplate.opsForValue().set(Constants.KDSH + userDb.getId().toString(), token);

        UserWithToken userWithToken = new UserWithToken(userDb, token);

        return new R(Message.ok, Message.loginSuc, Collections.singletonList(userWithToken));
    }*/

   /* @ApiOperation("手机号验证码登录")
    @PostMapping("/loginByPhoneVCode")
    public R loginByPhoneVCode(@RequestBody UserPhoneVCode user) {
        System.out.println("手机号+验证码登录");
        System.out.println(user);
        if (Helper.isPhoneInvalid(user.getPhone())) {
            return new R(Message.err, Message.phoneInvalid);
        }
        if (Helper.isVCodeInvalid(user.getVerifyCode())) {
            return new R(Message.err, Message.vCodeInvalid);
        }

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(User::getPhone, user.getPhone());
        int count = userMapper.selectCount(wrapper);
        if (count <= 0) {
            System.out.println("该手机号用户不存在");
            return new R(Message.err, Message.userDontExist);
        }

        //从数据库校验验证码
        QueryWrapper<VerifyCode> codeWrapper = new QueryWrapper<>();
        codeWrapper.lambda().eq(VerifyCode::getPhone, user.getPhone())
                .eq(VerifyCode::getCodeType, Constants.SMS_CODE_TYPE.LOGIN);
        if (codeMapper.selectCount(codeWrapper) <= 0) {
            System.out.println("没有获取过验证码");
            return new R(Message.err, Message.vCodeNotExists);
        }
        VerifyCode codeDb = codeMapper.selectOne(codeWrapper);
        if (!user.getVerifyCode().equals(codeDb.getCode())) {
            System.out.println("验证码不匹配");
            return new R(Message.err, Message.vCodeErr);
        }

        User userDb = userMapper.selectOne(wrapper);

        System.out.println("登录成功");

        String token = createToken(userDb);
        //将token存入redis
        redisTemplate.opsForValue().set(token, userDb.getId().toString());
        redisTemplate.opsForValue().set(Constants.KDSH + userDb.getId().toString(), token);

        UserWithToken userWithToken = new UserWithToken(userDb, token);

        return new R(Message.ok, Message.loginSuc, Collections.singletonList(userWithToken));
    }*/


    /*private R getUser(String openId) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(User::getOpenid, openId);

        System.out.println("从数据库中查询openid为" + openId + "的user");
        User user = userMapper.selectOne(queryWrapper);
        System.out.println(user.toString());


        if (user == null) {
            System.out.println("未注册，自动注册");

            User newUser = new User();
            newUser.setOpenid(openId);
            newUser.setStatus(1);
            System.out.println("创建新用户");
            System.out.println(newUser.toString());

            System.out.println("保存用户信息到数据库");
            userMapper.insert(newUser);

            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.select("id").eq("openId", openId);

            User userOnlyId = userMapper.selectOne(wrapper);
            System.out.println("从数据库中读取新用户id");
            System.out.println(userOnlyId.toString());
            newUser.setId(userOnlyId.getId());

            String token = createToken(newUser);
            //将token存入redis
            redisTemplate.opsForValue().set(token, newUser.getId().toString());
            redisTemplate.opsForValue().set(Constants.KDSH + newUser.getId().toString(), token);


            //todo 把用户数据存入redis
//            redisTemplate.opsfor
            UserWithToken userWithToken = new UserWithToken(newUser, token);

            return new R(Message.ok, Message.loginSuc, Collections.singletonList(userWithToken));
        } else {
            System.out.println("已注册，更新token");
            //创建查询条件：根据openid获取用户
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(User::getOpenid, openId);
            //查询用户
            User userDb = userMapper.selectOne(wrapper);
            //创建token
            String token = createToken(userDb);
            //将token存入redis
            redisTemplate.opsForValue().set(token, userDb.getId().toString());
            //组装返回值
            UserWithToken userWithToken = new UserWithToken(userDb, token);
            System.out.println(userWithToken.toString());
            return new R(Message.ok, Message.loginSuc, Collections.singletonList(userWithToken));
        }
    }*/



    private final long EXPIRE = 3600 * 24 * 30;

    @Autowired
    private UserAccessTokenMapper tokenMapper;

    public String createToken(User user) {

        String userIdStr = user.getId().toString();
        String token = UUID.randomUUID().toString();
        System.out.println("生成token for User " + userIdStr + ":" + token);

        //创建token查询条件
        QueryWrapper<UserAccessToken> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(UserAccessToken::getUserId, user.getId());

        //从redis中移除之前的（如果存在）
        String preTk = redisTemplate.opsForValue().get(userIdStr);
        if (preTk != null) {
            redisTemplate.delete(userIdStr);
            String preUid = redisTemplate.opsForValue().get(preTk);
            redisTemplate.delete(preUid);
        }

        //当前时间
        Date now = new Date();
        //过期时间
        Date expireTime = new Date(now.getTime() + EXPIRE * 1000);

        //创建Token对象
        UserAccessToken userAccessToken = new UserAccessToken();
        userAccessToken.setToken(token);
        userAccessToken.setUserId(user.getId());
        userAccessToken.setExpireAt(expireTime);

        int count = tokenMapper.selectCount(wrapper);
        if (count <= 0) {
            tokenMapper.insert(userAccessToken);
        } else {
            tokenMapper.update(userAccessToken, wrapper);
        }

        return token;
    }
}

